@file:Suppress("unused", "MemberVisibilityCanBePrivate")

package com.virtualightning.mvvm.tools.touch

import android.view.MotionEvent
import android.view.VelocityTracker
import com.virtualightning.mvvm.tools.shapes.VLPoint
import kotlin.math.abs

/**
 *  Anchor : Create by CimZzz
 *  Time : 2021/12/21 11:21
 *  单点触控辅助类
 */
class SingleTouchHelper {
	/**
	 * 移动距离 Y Slop
	 */
	private var ySlop: Int = -1
	/**
	 * 移动距离 x Slop
	 */
	private var xSlop: Int = -1

	/**
	 * 有效拦截事件
	 */
	private var touchTime: Long = -1L

	/**
	 * 判断当前是否已经拦截
	 */
	private var isIntercepted = false

	/**
	 *  Touch Down 点
	 */
	private val downPoint: VLPoint = VLPoint()

	/**
	 * 当前移动点
	 */
	private val movePoint: VLPoint = VLPoint()

	/**
	 * 速度追踪器
	 */
	private val velocityTracker: VelocityTracker = VelocityTracker.obtain()

	/**
	 * 最大移动距离
	 */
	private var maxMoveDistance: Float = 0f

	/**
	 * X 位移量
	 */
	private var xDistance: Float = 0f

	/**
	 * Y 位移量
	 */
	private var yDistance: Float = 0f

	/**
	 * 两点间距离
	 */
	private var distance: Float = 0f

	/**
	 * 触摸事件时间间隔
	 */
	private var touchEventDistance: Long = 0L

	/**
	 * 重置当前触摸事件
	 */
	fun reset() {
		isIntercepted = false
		maxMoveDistance = 0f
		touchEventDistance = 0L
		xDistance = 0f
		yDistance = 0f
		distance = 0f
		downPoint.reset()
		movePoint.reset()
		velocityTracker.clear()
	}

	/**
	 * 判断当前是否应该拦截触摸事件
	 * @param ev MotionEvent 触摸事件
	 * @return Boolean 如果应该拦截返回 true
	 */
	fun judgeIntercept(ev: MotionEvent): Boolean {
		if(ev.action == MotionEvent.ACTION_DOWN) {
			reset()
		}
		if(isIntercepted) {
			return true
		}
		when(ev.action) {
			MotionEvent.ACTION_DOWN -> {
				downPoint.setTouchEvent(ev)
				velocityTracker.addMovement(ev)
				return false
			}
			MotionEvent.ACTION_MOVE -> {
				movePoint.setTouchEvent(ev)
				velocityTracker.addMovement(ev)
				touchEventDistance = ev.eventTime - ev.downTime
				distance = downPoint.distance(movePoint)
				maxMoveDistance = maxMoveDistance.coerceAtLeast(distance)
				xDistance = downPoint.distanceX(movePoint)
				yDistance = downPoint.distanceY(movePoint)
				if(ySlop != -1 && abs(downPoint.distanceY(movePoint)) >= ySlop) {
					isIntercepted = true
					return true
				}
				if(xSlop != -1 && abs(downPoint.distanceX(movePoint)) >= xSlop) {
					isIntercepted = true
					return true
				}
			}
			else -> {
				touchEventDistance = ev.eventTime - ev.downTime
			}
		}
		return false
	}

	/**
	 * 按下触摸事件
	 * @param ev MotionEvent
	 */
	fun downAt(ev: MotionEvent) {
		if(ev.action == MotionEvent.ACTION_DOWN) {
			reset()
			downPoint.setTouchEvent(ev)
			velocityTracker.addMovement(ev)
		}
	}

	/**
	 * 触摸点移动
	 * @param ev MotionEvent 触摸事件
	 * @param resetDown Boolean 重置按下触摸点
	 */
	fun moveTo(ev: MotionEvent, resetDown: Boolean = false) {
		velocityTracker.addMovement(ev)
		movePoint.setTouchEvent(ev)
		touchEventDistance = ev.eventTime - ev.downTime
		distance = movePoint.distance(downPoint)
		maxMoveDistance = maxMoveDistance.coerceAtLeast(distance)
		xDistance = movePoint.distanceX(downPoint)
		yDistance = movePoint.distanceY(downPoint)
		if(resetDown) {
			downPoint.set(movePoint)
		}
	}

	///////////////////////////////////////////////////////////////////////////
	// 代码分割线 on 2021/12/21 11:37 上午 by CimZzz
	// 以下内容为:
	// 获取内部参数方法
	///////////////////////////////////////////////////////////////////////////

	/**
	 * 获取触摸事件时间间隔
	 * @return Long 时间间隔
	 */
	fun getTouchEventDistance(): Long {
		return touchEventDistance
	}

	/**
	 * 获取触摸事件最大移动距离
	 * @return Float
	 */
	fun getMaxMoveDistance(): Float {
		return maxMoveDistance
	}

	/**
	 * 获取 X 坐标位移量
	 * @return Float X 坐标位移量
	 */
	fun getXDistance(): Float {
		return xDistance
	}

	/**
	 * 获取 Y 坐标位移量
	 * @return Float Y 坐标位移量
	 */
	fun getYDistance(): Float {
		return yDistance
	}

	/**
	 * 获取两点间距离
	 * @return Float 两点间距离
	 */
	fun getDistance(): Float {
		return distance
	}

	///////////////////////////////////////////////////////////////////////////
	// 代码分割线 on 2021/12/21 11:29 上午 by CimZzz
	// 以下内容为:
	// 外部配置方法
	///////////////////////////////////////////////////////////////////////////

	/**
	 * 设置 X Slop
	 * @param xSlop Int
	 */
	fun setXSlop(xSlop: Int) {
		this.xSlop = xSlop
	}

	/**
	 * 设置 Y Slop
	 * @param ySlop Int
	 */
	fun setYSlop(ySlop: Int) {
		this.ySlop = ySlop
	}
}